/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2014 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "PlayPenTestPlugin.h"
#include "PlayPenTests.h"
#include "OgreResourceGroupManager.h"

PlaypenTestPlugin::PlaypenTestPlugin()
    :SamplePlugin("PlaypenTestPlugin")
{
    // tests that run on all GL RS
    char* only_common = getenv("OGRE_ONLY_COMMON_GL_TESTS");

    // add the playpen tests
    addSample(new PlayPen_2Spotlights());
    addSample(new PlayPen_AlphaToCoverage());
    addSample(new PlayPen_AttachObjectsToBones());
    addSample(new PlayPen_AlphaTex());
    addSample(new PlayPen_BasicPlane());
    addSample(new PlayPen_BillboardAccurateFacing()); // blocks are not lit (no darkness)
    addSample(new PlayPen_BillboardChain());
    addSample(new PlayPen_BillboardOrigins());
    addSample(new PlayPen_BillboardText());
    addSample(new PlayPen_BlendDiffuseColour());
    addSample(new PlayPen_BlitSubTextures()); // center tex missing
    addSample(new PlayPen_BuildTangentOnAnimatedMesh());
    addSample(new PlayPen_CameraSetDirection());
    addSample(new PlayPen_ClearScene());
    addSample(new PlayPen_CompositorTechniqueSwitch());
    addSample(new PlayPen_CompositorTextureShadows());
    addSample(new PlayPen_CubeDDS());
    addSample(new PlayPen_CustomProjectionMatrix());
    addSample(new PlayPen_DepthBias()); // glPolygonOffset misbehaving?
    addSample(new PlayPen_DepthShadowMap());

    addSample(new PlayPen_Distortion());
    addSample(new PlayPen_Dxt1());
    addSample(new PlayPen_Dxt1Alpha());
    addSample(new PlayPen_Dxt1FromMemory());
    addSample(new PlayPen_Dxt3());
    addSample(new PlayPen_Dxt3FromMemory()); // tex missing Win?
    if(!only_common) addSample(new PlayPen_Dxt5());
    addSample(new PlayPen_FarFromOrigin());

    if(!only_common) addSample(new PlayPen_GeometryShaders());
    if(!only_common) addSample(new PlayPen_HardwareScaleBlit()); // unsupported on GLES2

    addSample(new PlayPen_LightClipPlanes());
    addSample(new PlayPen_LightClipPlanesMoreLights());
    addSample(new PlayPen_LightScissoring());
    addSample(new PlayPen_LiSPSM()); // skids on Win
    addSample(new PlayPen_LotsAndLotsOfEntities());
    addSample(new PlayPen_ManualBlend());
    addSample(new PlayPen_ManualBoneMovement());
    addSample(new PlayPen_ManualIlluminationStage()); // stencil shadows
    addSample(new PlayPen_ManualObject2D());
    addSample(new PlayPen_ManualObjectIndexed());
    addSample(new PlayPen_ManualObjectIndexedUpdateLarger());
    addSample(new PlayPen_ManualObjectIndexedUpdateSmaller());
    addSample(new PlayPen_ManualObjectNonIndexed());
    addSample(new PlayPen_ManualObjectNonIndexedUpdateLarger());
    addSample(new PlayPen_ManualObjectNonIndexedUpdateSmaller());
    addSample(new PlayPen_MaterialSchemes());
    //addSample(new PlayPen_MaterialSchemesListener()); // works in SampleBrowser, but not TestContext, SEGV on Linux
    addSample(new PlayPen_MorphAnimationWithNormals()); // bugged on Lin
    addSample(new PlayPen_MorphAnimationWithoutNormals()); // bugged on Lin
    addSample(new PlayPen_MultiSceneManagersSimple()); // upper right only has ambient lighting, ignores light source
    addSample(new PlayPen_MultiViewports());
    addSample(new PlayPen_NegativeScale());
    addSample(new PlayPen_NonUniqueResourceNames());
    addSample(new PlayPen_NormalMapMirroredUVs()); // texture is missing
    addSample(new PlayPen_Ortho());
    addSample(new PlayPen_PBR());
    addSample(new PlayPen_PointSprites()); // not sure if RTSS (via gl_PointSize shader input) or glPointSize that makes points too small
    addSample(new PlayPen_PoseAnimationWithNormals()); // bugged on Lin
    addSample(new PlayPen_PoseAnimationWithoutNormals()); // bugged on Lin
    addSample(new PlayPen_ProjectSphere()); // does not seem to have ever worked in any RS
    addSample(new PlayPen_Projection());
    addSample(new PlayPen_ReflectedBillboards());
    addSample(new PlayPen_ReinitialiseEntityAlteredMesh()); // RTSS vertex shader bug

    if(!only_common) addSample(new PlayPen_ReloadResources());

    addSample(new PlayPen_RibbonTrail());
    addSample(new PlayPen_SRGBtexture()); // bug on Win
    addSample(new PlayPen_SceneNodeTracking());
    addSample(new PlayPen_SerialisedColour());
    addSample(new PlayPen_ShadowLod()); // causes bugs?
    addSample(new PlayPen_SkeletalAnimation());

    if(!only_common) addSample(new PlayPen_SkeletonAnimationOptimise());

    addSample(new PlayPen_StaticGeometry()); // possibly incorrect lighting?
    addSample(new PlayPen_StencilGlow());
    addSample(new PlayPen_StencilShadows());

    if(!only_common) addSample(new PlayPen_StencilShadowsMixedOpSubMeshes());

    addSample(new PlayPen_SubEntityVisibility());
    addSample(new PlayPen_TextureShadows());
    addSample(new PlayPen_TextureShadowsIntegrated());
    addSample(new PlayPen_TextureShadowsIntegratedPSSM()); // should have textures

    addSample(new PlayPen_TextureShadowsTransparentCaster()); // crashes on Windows

    addSample(new PlayPen_TransparencyMipMaps());
    addSample(new PlayPen_TwoSidedLighting());
    addSample(new PlayPen_VertexTexture()); // needs to be implemented in OpenGL
    addSample(new PlayPen_ViewportNoShadows());
    addSample(new PlayPen_WindowedViewportMode()); // possibly should only show quarter of screen?
    addSample(new PlayPen_16Textures());

    // addSample(new PlayPen_Bsp()); // results in conflicting resource ids if this and the one below are enabled
    addSample(new PlayPen_InfiniteAAB());

    if (!only_common && Root::getSingletonPtr()->getRenderSystem()->getCapabilities()->hasCapability(RSC_FIXED_FUNCTION))
    {
        addSample(new PlayPen_MaterialSchemesWithLOD());
        addSample(new PlayPen_MaterialSchemesWithMismatchedLOD());
    }

    if (!only_common && Root::getSingletonPtr()->getRenderSystem()->getName().find("OpenGL ES 2") == String::npos)
    {
        addSample(new PlayPen_SpotlightViewProj()); // Only Cg at this time
        addSample(new PlayPen_TextureShadowsCustomCasterMat()); // Only Cg at this time
        addSample(new PlayPen_TextureShadowsCustomReceiverMat()); // Only Cg at this time
    }

    //TODO
    // These should work, but my hardware doesn't seem to support 'em.
    // (and I'm unaware of a way to reliably check capabilities in this area...)

    // addSample(new PlayPen_2bppAlphaPVR());
    // addSample(new PlayPen_2bppPVR());
    // addSample(new PlayPen_4bppAlphaPVR());
    // addSample(new PlayPen_4bppPVR());
    addSample(new PlayPen_Float16DDS());
    addSample(new PlayPen_Float32DDS());
    addSample(new PlayPen_Float64DDS());
    addSample(new PlayPen_Float128DDS());

    //TODO
    // There was some shader issue (possibly my hardware, but either way I can't verify these two).
    // addSample(new PlayPen_MRT());
    // addSample(new PlayPen_MRTCompositorScript());

#ifdef OGRE_BUILD_COMPONENT_MESHLODGENERATOR
    addSample(new PlayPen_StaticGeometryWithLOD()); // possibly incorrect lighting?
    addSample(new PlayPen_ManualLOD());
    addSample(new PlayPen_ManualLODFromFile());
#endif
}
//---------------------------------------------------------------------

PlaypenTestPlugin::~PlaypenTestPlugin()
{
    for (auto s : mSamples)
    {
        delete s;
    }
    mSamples.clear();
}
//---------------------------------------------------------------------

#ifndef OGRE_STATIC_LIB

static PlaypenTestPlugin* testPlugin = 0;

extern "C" void _OgreSampleExport dllStartPlugin(void);
extern "C" void _OgreSampleExport dllStopPlugin(void);

extern "C" _OgreSampleExport void dllStartPlugin()
{
    testPlugin = OGRE_NEW PlaypenTestPlugin();
    Ogre::Root::getSingleton().installPlugin(testPlugin);
}

extern "C" _OgreSampleExport void dllStopPlugin()
{
    Ogre::Root::getSingleton().uninstallPlugin(testPlugin);
    OGRE_DELETE testPlugin;
}

#endif
